#include <stdint.h>
#include "stm32f4xx_hal.h"
#include "Drv_I2C.h"

typedef struct
{
	I2C_HandleTypeDef hi2c;
	GPIO_TypeDef *gpio;
	uint16_t sda_pin;
	uint16_t scl_pin;
	uint8_t alternate;
} I2C_GPIO_t;

typedef struct
{
	uint8_t speed_mode;
	uint8_t slave_address;
} I2C_Info_t;

typedef enum
{
	Standard_Mode,
	Fast_Mode,
} I2C_SpeedMode_t;

static I2C_Info_t g_I2cInfo = {Standard_Mode, 0x00};

static I2C_GPIO_t g_I2cgpio = {{0}, GPIOB, GPIO_PIN_7, GPIO_PIN_6, GPIO_AF4_I2C1};

/**
***********************************************************
* @brief I2C硬件初始化
* @param
* @return 
***********************************************************
*/
void I2C_DrvInit(uint8_t address)
{
	GPIO_InitTypeDef GPIO_Init = { 0 };

	// 使能I2C时钟
	__HAL_RCC_I2C1_CLK_ENABLE();
	// 时钟初始化
	__HAL_RCC_GPIOB_CLK_ENABLE();
	
	// 默认配置
	GPIO_Init.Mode = GPIO_MODE_AF_OD;
	GPIO_Init.Pull = GPIO_NOPULL;
	GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_Init.Alternate = g_I2cgpio.alternate; // 复用模式
	GPIO_Init.Pin = g_I2cgpio.sda_pin; // SDA引脚配置	
	HAL_GPIO_Init((GPIO_TypeDef *)g_I2cgpio.gpio, &GPIO_Init);
	
	GPIO_Init.Pin = g_I2cgpio.scl_pin; // SCL引脚配置	
	HAL_GPIO_Init((GPIO_TypeDef *)g_I2cgpio.gpio, &GPIO_Init);
	
	g_I2cInfo.slave_address = address;
	g_I2cgpio.hi2c.Instance = I2C1;
	// 速率设置
	if(g_I2cInfo.speed_mode == Standard_Mode)
		g_I2cgpio.hi2c.Init.ClockSpeed = 100000;
	else if(g_I2cInfo.speed_mode == Fast_Mode)
		g_I2cgpio.hi2c.Init.ClockSpeed = 400000;
	
	g_I2cgpio.hi2c.Init.DutyCycle = I2C_DUTYCYCLE_2;
	g_I2cgpio.hi2c.Init.OwnAddress1 = g_I2cInfo.slave_address;
	g_I2cgpio.hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
	g_I2cgpio.hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
	g_I2cgpio.hi2c.Init.OwnAddress2 = 0;
	g_I2cgpio.hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
	g_I2cgpio.hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
	HAL_I2C_Init(&g_I2cgpio.hi2c);
	
}

/* @bref 写入一个字节
 * @param reg_addr 待写入的寄存器地址
 * @param reg_data 待写入的数据
 * @retval 写入成功返回I2C_RET_OK，失败返回I2C_RET_ERROR
 */
uint8_t I2C_WriteByte(uint16_t reg_addr, uint8_t reg_data)
{
	if (HAL_I2C_Mem_Write(&g_I2cgpio.hi2c, g_I2cInfo.slave_address,
			reg_addr, I2C_MEMADD_SIZE_8BIT, &reg_data, 1, 1000) != HAL_OK)
	{
		return I2C_RET_ERROR;
	}

	return I2C_RET_OK;
}

/* @bref 读取一个字节
 * @param reg_addr 待读取的寄存器地址
 * @param p_data 数据缓冲区地址
 * @retval 读取成功返回I2C_RET_OK，失败返回I2C_RET_ERROR
 */
uint8_t I2C_ReadByte(uint16_t reg_addr, uint8_t *p_data)
{
	if(p_data == NULL)
		return I2C_RET_ERROR;
	
	if (HAL_I2C_Mem_Read(&g_I2cgpio.hi2c, (g_I2cInfo.slave_address | 0x01),
			reg_addr, I2C_MEMADD_SIZE_8BIT, p_data, 1, 1000) != HAL_OK)
	{
		return I2C_RET_ERROR;
	}
	
	return I2C_RET_OK;
}

/* @bref 读取多个字节
 * @param reg_addr 待读取的寄存器地址
 * @param p_data 数据缓冲区地址
 * @retval 读取成功返回I2C_RET_OK，失败返回I2C_RET_ERROR
 */
uint8_t I2C_ReadMultByte(uint16_t reg_addr, uint8_t *p_data, uint8_t nsize)
{
	if(p_data == NULL)
		return I2C_RET_ERROR;
	
	if (HAL_I2C_Mem_Read(&g_I2cgpio.hi2c, (g_I2cInfo.slave_address | 0x01),reg_addr, 
		I2C_MEMADD_SIZE_8BIT, p_data, nsize, 1000) != HAL_OK)
	{
		return I2C_RET_ERROR;
	}

	return I2C_RET_OK;
}

